/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package eu.easyedu.dictionary.api.importer;

import eu.easyedu.dictionary.api.model.Dictionary;
import eu.easyedu.dictionary.api.model.Language;
import eu.easyedu.dictionary.api.model.Word;
import eu.easyedu.dictionary.api.model.WordRelationship;
import eu.easyedu.dictionary.api.nservice.spi.WordBookService;
import eu.easyedu.dictionary.api.util.DatabaseUtils;
import eu.easyedu.dictionary.api.util.DerbyDriver;
import eu.easyedu.dictionary.api.util.DictionaryManager;
import eu.easyedu.dictionary.api.util.LanguageUtils;
import java.util.Collections;
import org.netbeans.api.db.explorer.DatabaseConnection;
import org.netbeans.api.progress.ProgressHandle;
import org.netbeans.api.progress.ProgressHandleFactory;
import org.openide.filesystems.FileObject;
import org.openide.util.Exceptions;
import org.openide.util.Lookup;
import org.openide.util.RequestProcessor;

/**
 *
 * @author hlavki
 */
public abstract class DictionaryImporter implements ImporterCallback {

    WordBookService wordBookService;
    Dictionary dictionary;
    int relationshipCount;
    ProgressHandle progressHandle;

    public DictionaryImporter() {
        relationshipCount = 0;
    }

    /**
     * Return name of dictionary format e.g. xdxf, dsl, starDict, etc.
     * @return dictionary format name
     */
    public abstract String getFormat();

    /**
     * Return display name for importer
     * @return display name
     */
    public abstract String getDisplayName();

    protected abstract void process(FileObject file);

    protected abstract String processDictionary(FileObject file);

    public final void importDictionary(final FileObject file) {
        wordBookService = Lookup.getDefault().lookup(WordBookService.class);
        relationshipCount = 0;
        String name = processDictionary(file);
        DerbyDriver driver = DerbyDriver.EMBEDDED;
        DictionaryManager dictManager = DictionaryManager.getDefault();
        String url = getDerbyUrl(name, driver, null, null, true);
        DatabaseConnection conn = dictManager.createConnection(driver, url);
        dictionary = new Dictionary(name, conn.getName());
        progressHandle = ProgressHandleFactory.createHandle("Importing dictionary...");
        dictManager.addDictionary(dictionary, null, true, progressHandle);

        RequestProcessor.getDefault().post(new Runnable() {

            public void run() {
                try {
                    progressHandle.start();
                    DatabaseUtils.startTransaction(dictionary);
                    process(file);
                    progressHandle.progress("Commiting transaction...");
                    DatabaseUtils.commitTransaction(dictionary);
                    progressHandle.finish();
                } catch (Exception e) {
                    Exceptions.printStackTrace(e);
                }
            }
        });
    }

    public final void onDictionaryCreate(String name) {
//        progressHandle.progress("Creating dictionary " + name);
        // TODO: do nothing
    }

    public final void onRelationship(WordRelationship relationship) {
        if (relationshipCount % 100 == 0) {
            progressHandle.progress("Imported " + relationshipCount + " words...");
        }
        Word wrd = wordBookService.addWord(dictionary, relationship.getWord());
        relationship.setWord(wrd);
        wordBookService.addRelationships(dictionary, Collections.singletonList(relationship));
        relationshipCount++;
    }

    public final Language onSourceLanguage(Language srcLanguage) {
        progressHandle.progress("Inserting source language " + srcLanguage.toString());
        srcLanguage.setName(LanguageUtils.getLanguage(srcLanguage.getCode()));
        return wordBookService.addLanguage(dictionary, srcLanguage);
    }

    public final Language onTargetLanguage(Language targetLanguage) {
        progressHandle.progress("Inserting target language " + targetLanguage.toString());
        targetLanguage.setName(LanguageUtils.getLanguage(targetLanguage.getCode()));
        return wordBookService.addLanguage(dictionary, targetLanguage);
    }

    protected final String getDerbyUrl(String name, DerbyDriver driver, String host, String port, boolean createDb) {
        StringBuffer url = new StringBuffer("jdbc:derby:");
        switch (driver) {
            case NETWORK:
                url.append("//").append(host).append(":");
                url.append(port).append("/").append(name.toLowerCase().replace(' ', '-'));
                break;
            case EMBEDDED:
                url.append(name.toLowerCase().replace(' ', '-'));
                break;

        }
        if (createDb) {
            url.append(";create=true");
        }
        return url.toString();
    }

    public final ImporterCallback getCallback() {
        return this;
    }

    @Override
    public String toString() {
        return getDisplayName() + " [" + getFormat() + "]";
    }
}
